var express = require('express');
var app = express();

// var server = require('http').createServer(app);

var fs = require('fs');
var https = require('https')

//https
var privateKey  = fs.readFileSync('./ssl/private.key', 'utf8');
var certificate = fs.readFileSync('./ssl/file.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var httpsServer = https.createServer(credentials, app);
var SSLPORT = 443;
var httpsServer2 = https.createServer(credentials, app);
httpsServer.listen(SSLPORT, function() {
    console.log('HTTPS Server is running on: https://localhost:%s', SSLPORT);
});

httpsServer2.listen(3333, function() {
    console.log('HTTPS Server is running on: https://localhost:%s', 3333);
});

var SkyRTC = require('skyrtc').listen(httpsServer2);

// Redirect from http port 80 to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);



var io = require('socket.io')(httpsServer2);


var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var multer = require('multer');
var datalist = new Array();
var outdatalist = new Array();
var formidable = require('formidable');

var session = require("express-session");
var util = require('util');
var sillyDate = require('silly-datetime');
var path = require('path');

//for chat
var roomHandler = require('./chatkit/handlers/roomHandler.js');
var socketHandler = require('./chatkit/handlers/socketHandler.js');
var adminHandler = require('./chatkit/handlers/adminHandler.js');
var msgHandler = require('./chatkit/handlers/msgHandler.js');
var fileHandler = require('./chatkit/handlers/fileHandler.js');
var usernameHandler = require('./chatkit/handlers/usernameHandler.js');



//直播状态
var isLiving = false;
var livingID;


// var port = 80;
// server.listen(port, function () {
//     console.log('Server listening at port %d', port);
// });




app.use(session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
}))

//模板引擎
app.set("view engine","ejs");


//skyRTc
SkyRTC.rtc.on('new_connect', function(socket) {
    console.log('创建新连接');
});

SkyRTC.rtc.on('remove_peer', function(socketId) {
    console.log(socketId + "用户离开");
});

SkyRTC.rtc.on('new_peer', function(socket, room) {
    console.log("新用户" + socket.id + "加入房间" + room);
});

SkyRTC.rtc.on('socket_message', function(socket, msg) {
    console.log("接收到来自" + socket.id + "的新消息：" + msg);
});

SkyRTC.rtc.on('ice_candidate', function(socket, ice_candidate) {
    console.log("接收到来自" + socket.id + "的ICE Candidate");
});

SkyRTC.rtc.on('offer', function(socket, offer) {
    console.log("接收到来自" + socket.id + "的Offer");
});

SkyRTC.rtc.on('answer', function(socket, answer) {
    console.log("接收到来自" + socket.id + "的Answer");
});

SkyRTC.rtc.on('error', function(error) {
    console.log("发生错误：" + error.message);
});



app.get('/register',function (req,res) {
    res.render("regist", {
        "login": req.session.login == "1" ? true : false,
        "username": req.session.login == "1" ? req.session.username : "",
        "active": "注册"
    });
});
//check login
// app.get('/',function (req,res,next) {
//     if(req.session.login == true){
//         next();
//     }else {
//         res.send('您还没有登录,请登录');
//     }
//
// });
// app.get('/login',function (req,res) {
//     req.session.login = true;
//     res.send("成功登录");
// });
// app.get('/logout',function (req,res) {
//     req.session.login = false;
//     res.send("登出成功");
// });

app.use(express.static(__dirname + '/client'));

app.use(bodyParser.json());

Fault = require('./models/fault');
Sensor = require('./models/sensor');
SensorData = require('./models/sensorData')



var sensorData = {
    data1 : [],
    time :''
}


//connect to mongoose
// mongoose.connect('mongodb://localhost/CNCMonitor');
mongoose.connect('mongodb://xieru:yanjiemao0577--@localhost:27017/CNCMonitor');
var db = mongoose.connection;







app.get('/api/faults',function (req,res) {
    Fault.getFaults(function(err,faults){
        if (err) {
            throw err;
        }
        res.json(faults);
    });
});


app.get('/api/faults/:_id',function (req,res) {
    Fault.getFaultById(req.params._id,function(err,fault){
        if (err) {
            throw err;
        }
        res.json(fault);
    });
});

app.get('/api/beginLiving/:_id',function (req,res) {
    isLiving = true;
    livingID = req.params._id;
    console.log("livingID:"+livingID);

    io.emit("beginLiving",livingID)
    res.json({status:"ok"})
});

app.get('/api/isNowLiving',function (req,res) {

    res.json({
        livingId:livingID
    })
})

app.get('/api/endLiving/:_id',function (req,res) {
    isLiving = false;
    livingID = null;
    console.log("livingEND");
    res.json({status:"ok"})
});


app.get('/api/findFaultsWithDate/:_beginDate/:_endDate',function (req,res) {
    console.log(req.params._beginDate);
    console.log(req.params._endDate);

    Fault.findFaultByDate(req.params._beginDate,req.params._endDate,function (err,faults) {
        if (err) {
            throw err;
        }
        res.json(faults);
    });
});

app.post('/api/find',function (req,res) {



    Fault.findFault(req.body,function (err,faults) {
        if (err){
            throw err;
        }

        res.json(faults);
    })
    

});






app.post('/api/faults',function(req,res){
    // var fault = req.body;
    // console.log(fault);

    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        //得到表单之后做的事情
        console.log(fields);
        var fault = fields;

        Fault.addFault(fault,function(err,fault) {
            if (err) {
                throw err;
            }
            var faultId = fault._id.toString();

            SensorData.addDataModel(faultId);
            res.json(fault);
        })

    });



});

app.put('/api/faults/:_id',function(req,res){
    var id = req.params._id;
    var fault = req.body;
    Fault.updateFault(id,fault,{},function(err,fault) {
        if (err) {
            throw err;
        }
        res.json(fault);
    })
});

app.delete('/api/faults/:_id',function(req,res){
    var id = req.params._id;
    Fault.deleteFault(id,function(err,fault) {
        if (err) {
            throw err;
        }
        res.json(fault);
    })
});




//处理实时传感器数据

app.get('/datalist',function (req,res) {
    sensorData.data1 = outdatalist;
    sensorData.time = (new Date()).toLocaleString( );
    res.json(sensorData);
    // res.json(outdatalist);
});


//保存传感器数据

app.post('/api/datalist',function (req,res) {
   var datalist = req.body;
    console.log(datalist);

});


//保存温度数据

app.post('/api/temperatureList',function (req,res) {
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        //得到表单之后做的事情

        console.log(fields);

    });


});

//获取历史数据
app.get('/api/tempDataHistory/:_id',function (req,res) {
    var _id = req.params._id;
    console.log("find history"+_id)

    SensorData.historyDataByFaultId(_id,function (data) {
        // var tempeDataLists = data.tempeDataList;

        if(data == 'notfind'){
            res.writeHead(200, {'Content-type' : 'text/plain'});
            res.write('notfind')
        }else{
            res.json(data);
        }


    })
});

app.get('/api/currentDataHistory/:_id',function (req,res) {
    var _id = req.params._id;

    SensorData.historyDataByFaultId(_id,function (data) {
        var currentDataLists = data.currentDataList;

        res.json(currentDataLists);

    })
});


var monitoringId = "";
app.get('/api/beginMonitor/:_id',function (req,res) {
    var _id = req.params._id;
    console.log(_id);
    monitoringId = _id;



    res.json({"status":"ok"})



})


var net = require('net');
// var client = new net.Socket();
var temperatureServer = net.createServer(function (socket){

    var tempeData = [];
    socket.on('data',function (data) {
        // var temperature = JSON.parse(data.toString())
        var temperature = data.toString();


        tempeData.push(parseFloat(temperature));

        console.log("temperature："+temperature);
        io.emit("temperature",temperature)
        io.emit("monitoringId",monitoringId);
    })

    socket.on('end',function () {
        //保存到数据库
        SensorData.addTemperature(monitoringId,tempeData);
        io.emit("monitorEnd","监测结束")
    });
});

//


temperatureServer.on('connection',function (client) {
   console.log("监测开始");
    io.emit("monitorBegin","监测开始")
});
temperatureServer.listen(1339);

var currentServer = net.createServer(function (socket){

    var currentData = [];
    socket.on('data',function (data) {
        // var temperature = JSON.parse(data.toString())
        var current = data.toString();
        currentData.push(parseFloat(current));

        console.log("current："+current);
        io.emit("current",current)
    })

    socket.on('end',function () {
        //保存到数据库
        SensorData.addCurrent(monitoringId,currentData);
        io.emit("monitorEnd","监测结束")
    });
});
currentServer.listen(1340);

//温度 socket



var server = net.createServer(function (socket) {
    socket.on('data',function (data) {
        var response = data.toString().trim();
        var strs = new Array();
        strs=response.split(",");
        strs.splice(1,1);

        datalist = datalist.concat(strs);

        if (datalist.length >= 11024){
            var temlist = datalist;
            var k;

            var temOut = [];
            for (k=0;k<temlist.length-1;k++){
                var num = new Number(temlist[k]);
                // console.log(num);
                if (num > 1){
                    continue;
                }

                temOut.push(num * 10000000000000);
            };
            outdatalist = temOut;
            // console.log(outdatalist);

            console.log(Math.max.apply(Math, outdatalist));
            datalist = [];
        }

    });

    socket.on('end',function () {
        outdatalist = [];
        console.log('end');
    })
});




/** API path that will upload the files */
// app.post('/upload', function(req, res) {
//     res.json(req.files);
// });

app.get('/file/', function(req, res, next) {
    // 实现文件下载
    var fileName = req.query.fileName;
    var fileDownloadName = req.query.fileDownloadName;
    var filePath = __dirname + '/client/fileUploads/' + fileName;
    console.log(filePath + '------------------------');
    var stats = fs.statSync(filePath);
    if(stats.isFile()){
        // res.set({
        //     'Content-Type': 'application/octet-stream',
        //     'Content-Disposition': 'attachment; filename='+fileName,
        //     'Content-Length': stats.size
        // });
        // fs.createReadStream(filePath).pipe(res);
        res.download(filePath, fileDownloadName);
    } else {
        res.end(404);
    }
});


app.get('/booksDownload',function (req,res) {
    // 实现文件下载
    var fileName = req.query.fileName;
    var filePath = __dirname + '/client/resources/' + fileName;
    console.log(filePath + '------------------------');
    var stats = fs.statSync(filePath);
    if(stats.isFile()){
        // res.set({
        //     'Content-Type': 'application/octet-stream',
        //     'Content-Disposition': 'attachment; filename='+fileName,
        //     'Content-Length': stats.size
        // });
        // fs.createReadStream(filePath).pipe(res);
        res.download(filePath);
    } else {
        res.end(404);
    }
});

app.post('/movieUpload',function (req,res) {
    var form = new formidable.IncomingForm();
    form.uploadDir = "./client/movieUploads";

    form.parse(req,function (err,fields,files) {
        var faultId = fields.faultId;
        console.log(fields);
        console.log(files.movie);
        var movie = files.movie.name;

        var newpath = "client/movieUploads/" + files.movie.name;
        var oldpath = files.movie.path;
        fs.renameSync(oldpath,newpath);

        Fault.addMovie(faultId,movie)

        setTimeout(function () {
            io.emit("newMovieUpload",movie);

        },500);

        res.json(files);
    })



});

app.post('/imageUpload', function(req, res, next) {
    var form = new formidable.IncomingForm();
    form.uploadDir = "./client/imageUploads";

    form.parse(req,function (err,fields,files) {
        // req.body = fields;
        // req.files = files;

        // res

        console.log(fields);

        var imageNames = [];
        var originalFileNames = [];
        var saveFileNames = [];
        var commonImageExtNames = [".gif",".jpg",".jpeg",".bmp",".png"];

        var faultId = fields.faultId.replace("\"","").replace("\"","");

        for (var i in files) {
            var file = files[i];
            var extname = path.extname(file.name).toLowerCase();
             var ttt = sillyDate.format(new Date(), 'YYYYMMDDHHmmss');
            var ran = parseInt(Math.random() * 89999 + 10000);
            // var extname = path.extname(files.name);
            //
            // //执行改名
            var oldpath = __dirname + "/" + file.path;
            // //新的路径由三个部分组成：时间戳、随机数、拓展名

            var newName = ttt + ran + extname;

            //是图片
            if(commonImageExtNames.indexOf(extname) != -1){

                var newpath = __dirname + "/client/imageUploads/" + newName;

                fs.renameSync(oldpath,newpath);
                imageNames.push(newName);


            }else {//是普通文件

                var newPath = __dirname + "/client/fileUploads/" + newName;
                fs.renameSync(oldpath,newPath);

                originalFileNames.push(file.name);
                saveFileNames.push(newName);

            }


        }

        if(imageNames.length > 0){
            Fault.addImage(faultId,imageNames,function () {
                console.log("add image success")
            });
        }

        if(originalFileNames.length > 0){
            Fault.addFile(faultId,originalFileNames,saveFileNames);
        }


        setTimeout(function () {
            io.emit("imageUploaded","imageUploaded")
        },500);


        res.json(files);
    });

});

app.post('/api/diag',function (req,res) {
    // console.log(req.body);

    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        //得到表单之后做的事情

        var progress = parseFloat(fields.progress)/100;
        var text = fields.diagText;
        var faultId = fields.faultId.replace("\"","").replace("\"","");
        var title = fields.title;

        Fault.addDiag(faultId,progress,text,title);
        res.json("ok");



    });




    // Fault.addDiag(faultId,progress,text);
});


app.post('/api/sensor',function(req,res){
    var sensor = req.body;
    Sensor.addSensor(sensor,function(err,sensor) {
        if (err) {
            throw err;
        }
        res.json(sensor);
    })
});






app.get('/api/sensors',function (req,res) {
    Sensor.getSensors(function(err,faults){
        if (err) {
            throw err;
        }
        res.json(faults);
    });
});

app.get('/api/sensor/temrate',function (req,res) {
    // Sensor.getSensors(function(err,faults){
    //     if (err) {
    //         throw err;
    //     }
    //     var fault = faults[0];
    //     res.json(fault.rate);
    // });
    res.json({rate:1});

})



server.listen(1338);

console.log("data server is Running on port 1338");




// Chatbox
io.on('connection', function (socket) {


    adminHandler.log('New socket connected!');
    adminHandler.log('socket.id: '+ socket.id);
    socketHandler.socketConnected(socket);

    adminHandler.log("socket.ip: " + socket.remoteAddress);


    // once the new user is connected, we ask him to tell us his name
    // tell him how many people online now
    // TODO: may not need to say welcome when it's his second third connection
    socket.emit('login', {
        numUsers: socketHandler.getUserCount()
    });

    // once a new client is connected, this is the first msg he send
    // we'll find out if he's a new user or existing one looking at the cookie uuid
    // then we'll map the user and the socket
    socket.on('login', function (data) {


        var newUser = false;

        newUser = socketHandler.socketJoin(socket, data.url, data.referrer, data.uuid, data.username);

        var roomID = roomHandler.socketJoin(socket, data.roomID);

        var user = socket.user;

        if (newUser) {


            // ensure username unique in same chat room
            usernameHandler.registerUniqueName(user, user.username);


            //TODO: if the username distributed to user from server is different from the client one
            // we need to tell the client to update local name

            // welcome the new user
            socket.emit('welcome new user', {
                username: user.username,
                // numUsers: socketHandler.getUserCount() // this should be user count in same room
                onlineUsers: usernameHandler.getNamesInRoom(roomID)
            });

            // echo to others that a new user just joined
            io.in(roomID).emit('user joined', {
                username: user.username,
                // numUsers: socketHandler.getUserCount() // this should be user count in same room
            });

            adminHandler.log(user.username + ' joined in room ' + roomID);


        } else {

            // the user already exists, this is just a new connection from him
            // force sync all user's client side usernames
            socket.emit('welcome new connection', {
                username: user.username,
                // numUsers: socketHandler.getUserCount(), // this should be user count in same room
                onlineUsers: usernameHandler.getNamesInRoom(roomID)

            });

            adminHandler.log(user.username + ' logged in ('+(user.socketIDList.length) +').', user.roomID);

        }

    });

    // when the socket disconnects
    socket.on('disconnect', function () {

        var lastConnectionOfUser = socketHandler.socketDisconnected(socket);

        // the user only exist after login
        if (!socket.joined)
            adminHandler.log('Socket disconnected before logging in, sid: ' + socket.id);
        else
            adminHandler.log(socket.user.username + ' closed a connection ('+(socket.user.socketIDList.length)+').', socket.user.roomID);

        if (lastConnectionOfUser) {

            usernameHandler.releaseUsername(socket.user.roomID, socket.user.username);
            roomHandler.leftRoom(socket.user);

            io.in(socket.user.roomID).emit('stop typing', { username: socket.user.username });

            io.in(socket.user.roomID).emit('user left', {
                username: socket.user.username,
                numUsers: socketHandler.getUserCount()
            });
        }

    });

    // this is when one user wants to change his name
    // enforce that all his socket connections change name too
    socket.on('user edits name', function (data) {


        var user = socket.user;
        var oldName = user.username;

        if (oldName === data.newName)
            return;

        usernameHandler.userEditName(socket, data.newName);

        io.in(user.roomID).emit('log change name', {
            username: user.username,
            oldname: oldName
        });

        adminHandler.log(oldName + ' changed name to ' + user.username, socket.user.roomID);

    });


    socket.on('report', function (data) {

        adminHandler.log(socket.user.username + ": " + data.msg, socket.user.roomID);

    });

    // when the client emits 'new message', this listens and executes
    socket.on('new message', function (data) {

        io.in(socket.user.roomID).emit('new message', {//send to everybody including sender
            username: socket.user.username,
            message: data.msg
        });
        msgHandler.receiveMsg(socket, data.msg);
        roomHandler.newMsg(socket.user.roomID);

    });

    socket.on('base64 file', function (data) {

        adminHandler.log('received base64 file from ' + socket.user.username, socket.user.roomID);

        fileHandler.receiveFile(socket, data.file, data.fileName);

        io.in(socket.user.roomID).emit('base64 file',

            {
                username: socket.user.username,
                file: data.file,
                fileName: data.fileName
            }

        );

    });


    // when the client emits 'typing', we broadcast it to others
    socket.on('typing', function (data) {

        io.in(socket.user.roomID).emit('typing', { username: socket.user.username });

    });

    // when the client emits 'stop typing', we broadcast it to others
    socket.on('stop typing', function (data) {

        io.in(socket.user.roomID).emit('stop typing', { username: socket.user.username });

    });

    // for New Message Received Notification callback
    socket.on('reset2origintitle', function (data) {
        if (!socket.joined) return;
        var socketsToResetTitle = socket.user.socketIDList;
        for (var i = 0; i< socketsToResetTitle.length; i++)
            socketHandler.getSocket(socketsToResetTitle[i]).emit('reset2origintitle', {});

    });

    //============================================================================================
    //============================================================================================
    //   code below are for admin only, so we always want to verify token first in adminHandler
    //============================================================================================
    //============================================================================================


    // admin change visitor's username
    socket.on('admin change username', function (data) {

        adminHandler.adminChangeUsername(io, data.token, data.userID, data.newName);

    });

    socket.on('getServerStat', function (data) {

        adminHandler.getServerStat(socket, data.token);

    });

    // send script to target users
    socket.on('admin command', function (data) {

        adminHandler.sendCommand(io, data.token, data.userKeyList, data.socketKeyList, data.type, data.content);

    });

    // send real time data statistic to admin
    // this callback is currently also used for admin authentication
    socket.on('getUserList', function (data) {

        adminHandler.getUserData(socket, data.token);

    });


});
